package com.lyd.sweet.feign.interceptor;

import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.http.HttpHeaders;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

/**
 * feign的顶层过滤器。用于在使用feign进行内部微服务之间请求时统一添加token信息。
 *
 * 如果当前微服务应用的token，当微服务作为服务消费者调用其他微服务时，默认将token通过header传递。
 *
 * 如果是基于feign调用外部第三方restapi时需要通过header传递token，
 * 则根据对方要求在feign方法定义处通过@RequestHeader注解传递token，将会覆盖本类默认设置的内容。
 *
 * @author 木木
 */
public class FeignInterceptor implements RequestInterceptor {
    /**
     * 内部标识，内容调用不二次封装head头
     */
    public static final String FEIGN_HEADER = "FEIGN-HEADER";

    /**
     * 内部标识值
     */
    public static final String FEIGN_HEADER_VALUE = "SweetFeign";

    @Override
    public void apply(RequestTemplate requestTemplate) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (null != attributes) {
            HttpServletRequest request = attributes.getRequest();
            //取token的值，根据spring security约定token会放在header中或者通过请求参数“access_token”传递。
            //约定默认将token放在header中。因此优先从header中取，如果没有则通过请求参数access_token取
            String token = request.getHeader(HttpHeaders.AUTHORIZATION);
            if (token == null || token.isEmpty()) {
                token = request.getParameter("access_token");
            }
            if (token != null && !token.isEmpty()) {
                //统一通过header传token。spring security默认会从header取token。
                requestTemplate.header(HttpHeaders.AUTHORIZATION, token);
            }

            // 默认在header中加一个标识。用于识别服务消费者是否来自feign的调用，
            // 从而判断服务调用是来自内部微服务间的内部调用还是外部第三方的调用。
            requestTemplate.header(FEIGN_HEADER, FEIGN_HEADER_VALUE);
        }
    }
}
